package controllers;

import de.puc.defencetower.model.*;

import models.GameWebSocket;
import models.HighscoreHelper;
import org.h2.engine.User;
import play.api.Play;
import play.libs.F;
import play.libs.OpenID;
import play.mvc.*;

import org.codehaus.jackson.*;

import scala.reflect.io.VirtualFile;
import views.html.*;
import views.html.donate;
import views.html.highscore;
import views.html.home;
import views.html.login;
import views.html.newgame;
import views.html.playgame;

import java.io.*;
import java.util.HashMap;


public class Application extends Controller {

    public static GameController gameController = null;

    // close all and remake
    public static void initGameControllerSingelton(String mapSize){
        if(gameController == null){
            gameController = new GameController(mapSize);
        }else {

            gameController.cleanUp();
            gameController = new GameController(mapSize);
        }
    }

    public static Result home() {
        File file = new File("test");
        return ok(home.render("home"));
    }

    public static Result highscore() {
        return ok(highscore.render("highscore"));
    }

    public static Result donate() {
        return ok(donate.render("Donate Coins"));
    }

    public static Result game(String mapSize) {
        // new game or continue
        if(mapSize == null || mapSize.equals("selection")){
            return ok(newgame.render("newgame"));
        } else {
            return playGame(mapSize);
        }
    }

    public static Result playGame(String mapSize) {
        // resume game TODO irgendwie über routes parameter

        if(mapSize == null){
            flash("error", "Please choose a valid map.");
            return redirect(routes.Application.home());
        }

        // Map check name
        Map map = null;
        switch (mapSize){
            case "mini":

                break;
            case "small":

                break;
            case "middle":

                break;
            case "big":

                break;
            default:
                return Results.notFound("no map with this id" + mapSize);
        }

        return ok(playgame.render(mapSize));
    }

    public static class Login {

        public String password ;

        public String validate() {
            if (!password.equals("admin")) {
                return "Invalid user or password";
            } else{
                session("admin", "true");
                return null;
            }
        }
    }

    public static Result login(){
        return ok(
                views.html.login.render(play.data.Form.form(Login.class))
        );
    }



    public static Result authenticate() {
        play.data.Form<Login> loginForm = play.data.Form.form(Login.class).bindFromRequest();
        if (loginForm.hasErrors()) {
            return badRequest(login.render(loginForm));
        } else {
            //session().clear();

            return redirect(
                    routes.Application.home()
            );
        }
    }

    public static Result logout() {
        session("admin", "false");
        //Login.admin = false;
        flash("success", "You've been logged out");
        return redirect(
                routes.Application.home()
        );
    }

    public static boolean isAdmin(){
        if(session("admin") != null && session("admin").equals("true")){
            return true;
        } else{
            return false;
        }
    }

    // openId
    public static Result auth() {
        String providerUrl = "https://www.google.com/accounts/o8/id";
        String returnToUrl = "http://h2234516.stratoserver.net:9000/openID/verify";
        HashMap<String, String> attributes = new HashMap<>();
        attributes.put("Email", "http://schema.openid.net/contact/email");
        attributes.put("FirstName", "http://schema.openid.net/namePerson/first");
        attributes.put("LastName", "http://schema.openid.net/namePerson/last");
        attributes.put("UserId", "http://schemas.openid.net/ax/api/user_id");
        F.Promise<String> redirectUrl = OpenID.redirectURL(providerUrl, returnToUrl, attributes);
        return redirect(redirectUrl.get());
    }
    public Result verify() {
        F.Promise<OpenID.UserInfo> userInfoPromise = OpenID.verifiedId();
        OpenID.UserInfo userInfo = userInfoPromise.get();
        //session().clear();
        session("email", userInfo.attributes.get("Email"));
        session("firstname", userInfo.attributes.get("FirstName"));
        session("lastname", userInfo.attributes.get("LastName"));
        session("userid", userInfo.attributes.get("UserId"));
        rememberHighscore();

        String id = new HighscoreHelper().saveNewHighscore();

        return redirect(
                routes.Application.highscore()
        );
    }


    // called from gamecontroller
    public static String rememberHighscore(){
        session("monster", ""+gameController.map.getDeadMonsterNumber());
        session("wave", ""+gameController.map.getMonstersSpawned());
        session("mapsize", ""+gameController.mapSize);
        return "";
    }

    /**
     * Handle the websocket request.
     */
    public static WebSocket<JsonNode> websocketConnection(final String mapSize) {

        // if not exists
        initGameControllerSingelton(mapSize);



        // maybe more websockets in future
        return gameController.getGameConnection().getWebSocket();


    }
}
